//-
// ==========================================================================
// Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors.  All 
// rights reserved.
//
// The coded instructions, statements, computer programs, and/or related 
// material (collectively the "Data") in these files contain unpublished 
// information proprietary to Autodesk, Inc. ("Autodesk") and/or its 
// licensors, which is protected by U.S. and Canadian federal copyright 
// law and by international treaties.
//
// The Data is provided for use exclusively by You. You have the right 
// to use, modify, and incorporate this Data into other products for 
// purposes authorized by the Autodesk software license agreement, 
// without fee.
//
// The copyright notices in the Software and this entire statement, 
// including the above license grant, this restriction and the 
// following disclaimer, must be included in all copies of the 
// Software, in whole or in part, and all derivative works of 
// the Software, unless such copies or derivative works are solely 
// in the form of machine-executable object code generated by a 
// source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. 
// AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED 
// WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF 
// NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
// PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR 
// TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS 
// BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, 
// DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK 
// AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY 
// OR PROBABILITY OF SUCH DAMAGES.
//
// ==========================================================================
//+

///////////////////////////////////////////////////////
//
// DESCRIPTION:
//
///////////////////////////////////////////////////////

#include <maya/MPxNode.h>
#include <maya/MIOStream.h>
#include <maya/MString.h>
#include <maya/MTypeId.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFloatVector.h>
#include <maya/MFnPlugin.h>


//
// DESCRIPTION:
///////////////////////////////////////////////////////
class GeomNode : public MPxNode
{
	public:
                     GeomNode();
   virtual           ~GeomNode();

   virtual MStatus   compute( const MPlug&, MDataBlock& );
   virtual void      postConstructor();

   static  void *    creator();
   static  MStatus   initialize();

	//  Id tag for use with binary file format
   static  MTypeId   id;

	private:

	// Input attributes
	static MObject aPoint;
    static MObject aScale;
    static MObject aOffset;

	// Output attributes
	static MObject aOutColor;
};

// static data
MTypeId GeomNode::id( 0x81004 );

// Attributes
MObject  GeomNode::aPoint;
MObject  GeomNode::aScale;
MObject  GeomNode::aOffset;
MObject  GeomNode::aOutColor;

#define MAKE_INPUT(attr)								\
  CHECK_MSTATUS ( attr.setKeyable(true) ); 				\
  CHECK_MSTATUS ( attr.setStorable(true) );				\
  CHECK_MSTATUS ( attr.setReadable(true) ); 			\
  CHECK_MSTATUS ( attr.setWritable(true) );

#define MAKE_OUTPUT(attr)								\
  CHECK_MSTATUS (attr.setKeyable(false) );  			\
  CHECK_MSTATUS ( attr.setStorable(false));				\
  CHECK_MSTATUS ( attr.setReadable(true) ); 			\
  CHECK_MSTATUS ( attr.setWritable(false));

// DESCRIPTION:
//
///////////////////////////////////////////////////////
void GeomNode::postConstructor( )
{
	setMPSafe(true);
}

// DESCRIPTION:
//
///////////////////////////////////////////////////////
GeomNode::GeomNode()
{
}

// DESCRIPTION:
//
///////////////////////////////////////////////////////
GeomNode::~GeomNode()
{
}

// DESCRIPTION:
//
///////////////////////////////////////////////////////
void* GeomNode::creator()
{
    return new GeomNode();
}

// DESCRIPTION:
//
///////////////////////////////////////////////////////
MStatus GeomNode::initialize()
{
    MFnNumericAttribute nAttr; 

    // Input attributes

    aPoint = nAttr.createPoint( "pointObj", "p" );
    CHECK_MSTATUS ( nAttr.setStorable(false) );
    CHECK_MSTATUS ( nAttr.setHidden(true) );

    aScale = nAttr.createPoint( "scale", "s" );
    MAKE_INPUT(nAttr);
    CHECK_MSTATUS ( nAttr.setDefault(1.0f, 1.0f, 1.0f) );

    aOffset = nAttr.createPoint( "offset", "o" );
    MAKE_INPUT(nAttr);

	// Output attributes
    aOutColor  = nAttr.createColor( "outColor", "oc" );
    MAKE_OUTPUT(nAttr);

	// Add attributes to the node database.
    CHECK_MSTATUS ( addAttribute(aPoint) );
    CHECK_MSTATUS ( addAttribute(aScale) );
    CHECK_MSTATUS ( addAttribute(aOffset) );

    CHECK_MSTATUS ( addAttribute(aOutColor) );

	// All input affect the output color
    CHECK_MSTATUS ( attributeAffects (aPoint, aOutColor) );
    CHECK_MSTATUS ( attributeAffects (aScale, aOutColor) );
    CHECK_MSTATUS ( attributeAffects (aOffset,aOutColor) );

    return MS::kSuccess;
}

// DESCRIPTION:
//
///////////////////////////////////////////////////////
MStatus GeomNode::compute(
const MPlug&      plug,
      MDataBlock& block ) 
{
	// outColor or individial R, G, B channel
    if((plug != aOutColor) && (plug.parent() != aOutColor))
		return MS::kUnknownParameter;

    MFloatVector resultColor;

    MFloatVector & point  = block.inputValue( aPoint ).asFloatVector();
    MFloatVector & scale  = block.inputValue( aScale ).asFloatVector();
    MFloatVector & offset = block.inputValue( aOffset ).asFloatVector();

    // Scale + Offset original geometry position
    resultColor.x = point.x * scale.x + offset.x;
    resultColor.y = point.y * scale.y + offset.y;
    resultColor.z = point.z * scale.z + offset.z;

    // set ouput color attribute
    MDataHandle outColorHandle = block.outputValue( aOutColor );
    MFloatVector& outColor = outColorHandle.asFloatVector();
    outColor = resultColor;
    outColorHandle.setClean();

    return MS::kSuccess;
}

//
// DESCRIPTION:
///////////////////////////////////////////////////////
MStatus initializePlugin( MObject obj )
{
   const MString UserClassify( "utility/general" );

   MFnPlugin plugin( obj, PLUGIN_COMPANY, "4.5", "Any");
   CHECK_MSTATUS ( plugin.registerNode( "geomNode", GeomNode::id, 
                         GeomNode::creator, GeomNode::initialize,
                         MPxNode::kDependNode, &UserClassify ) );

   return MS::kSuccess;
}

//
// DESCRIPTION:
///////////////////////////////////////////////////////
MStatus uninitializePlugin( MObject obj )
{
   MFnPlugin plugin( obj );
   CHECK_MSTATUS ( plugin.deregisterNode( GeomNode::id ) );

   return MS::kSuccess;
}
